using System.Collections.Generic;
using UnityEngine;

/*
* Introduction：    循环视图对象池管理类，负责单元格的创建、回收和复用
* Version：         1.1
* Creator：         yixiang.hui
* Creation Time：   2025.9.3
*
* Last Editor：     yixiang.hui 
* Last Edit Time：  2025.9.3
* Note：            1.1版本改进了对象池管理，防止内存泄漏，优化了性能
*/

namespace Hyx.UIComponent
{
    public class LoopViewPool : MonoBehaviour
    {
        public int maxCount = 50;
        public LoopViewPoolCell cell;
        private Queue<LoopViewPoolCell> m_queue = new Queue<LoopViewPoolCell>();

        public LoopViewPoolCell[] childTemps;
        private Dictionary<int, Queue<LoopViewPoolCell>> m_childQueue = new Dictionary<int, Queue<LoopViewPoolCell>>();

        private Transform cacheTransform;

        void Awake()
        {
            cacheTransform = transform;
        }

        private void OnExitScene()
        {
            ClearPool();
        }

        public T FetchItem<T>() where T : LoopViewPoolCell
        {
            T rt = null;
            if (m_queue.Count > 0)
            {
                rt = m_queue.Dequeue() as T;
                rt.Reset();
            }
            else
            {
                GameObject itemgo = InstantiateItem();
                if (itemgo != null)
                {
                    rt = itemgo.GetComponent<T>();
                    itemgo.SetActive(true);
                    InitCell(rt);
                }
            }
            rt.cacheRectTransform.localScale = Vector3.one;
            rt.OnStart();
            return rt;
        }

        public void PutItem<T>(GameObject go, bool isBattleDamage = false) where T : LoopViewPoolCell
        {
            T rt = go.GetComponent<T>();
            if (rt == null) return;

            rt.Reset();
            if (m_queue.Count < maxCount)
            {
                m_queue.Enqueue(rt);
                if (!isBattleDamage)
                {
                    go.SetActive(false);
                }
                rt.cacheTransform.SetParent(cacheTransform);
            }
            else
            {
                Destroy(go);
            }
        }

        private GameObject InstantiateItem()
        {
            if (cell != null)
            {
                GameObject item = Instantiate(cell.gameObject);
                return item;
            }
            return null;
        }

        public T FetchChild<T>(int index) where T : LoopViewPoolCell
        {
            T rt = null;
            Queue<LoopViewPoolCell> queue = GetQueueByType(index);
            if (queue.Count > 0)
            {
                rt = queue.Dequeue() as T;
                rt.Reset();
            }
            else
            {
                GameObject itemgo = InstantiateChild(index);
                if (itemgo != null)
                {
                    rt = itemgo.GetComponent<T>();
                    itemgo.SetActive(true);
                    InitCell(rt);
                }
            }
            rt.cacheRectTransform.localScale = Vector3.one;
            rt.OnStart();
            return rt;
        }

        public void PutChild<T>(T rt, int index) where T : LoopViewPoolCell
        {
            if (rt == null)
                return;

            Queue<LoopViewPoolCell> queue = GetQueueByType(index);
            rt.Reset();
            if (queue.Count < maxCount)
            {
                queue.Enqueue(rt);
                rt.cacheObejct.SetActive(false);
                rt.cacheTransform.SetParent(cacheTransform);
            }
            else
            {
                Destroy(rt.cacheObejct);
            }
        }

        private void ClearPool()
        {
            cell = null;
            childTemps = null;
            m_queue.Clear();
            m_childQueue.Clear();
        }

        private GameObject InstantiateChild(int index)
        {
            if (childTemps != null && childTemps.Length > index && childTemps[index] != null)
            {
                GameObject item = Instantiate(childTemps[index].gameObject);
                return item;
            }
            return null;
        }

        private Queue<LoopViewPoolCell> GetQueueByType(int index)
        {
            Queue<LoopViewPoolCell> queue;
            if (!m_childQueue.TryGetValue(index, out queue))
            {
                queue = new Queue<LoopViewPoolCell>();
                m_childQueue.Add(index, queue);
            }
            return queue;
        }

        private void InitCell(LoopViewPoolCell cell)
        {
            cell.pool = this;
            cell.Init();
        }
    }
}